package com.tanhua.service;

import com.tanhua.domain.db.User;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.Comment;
import com.tanhua.domain.mongo.Publish;
import com.tanhua.domain.mongo.Visitor;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.domain.vo.PublishVO;
import com.tanhua.domain.vo.VisitorVO;
import com.tanhua.dubbo.api.*;
import com.tanhua.template.OssTemplate;
import com.tanhua.util.RelativeDateFormat;
import com.tanhua.util.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

@Slf4j
@Service
public class MovementsService {
    @Reference
    private MovementsApi movementsApi;
    @Reference
    private UserInfoApi userInfoApi;
    @Reference
    private CommentApi commentApi;
    @Reference
    private PublishApi publishApi;
    @Reference
    private VisitorsApi visitorsApi;


    @Autowired
    private OssTemplate ossTemplate;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private MovementMQService movementMQService;

    /**
     * 推荐动态
     *
     * @param page
     * @param pagesize
     * @return
     */

    public ResponseEntity recommendPublish(Integer page, Integer pagesize) {
        User user = UserHolder.getUser();
        //查询推荐动态
        PageResult pageResult = findPublishByRedis(page, pagesize);
        if (pageResult == null) {

            pageResult = movementsApi.recommendPublish(user.getId(), page, pagesize);
        }
        //根据userId查询发布动态用户信息
        List<Publish> items = pageResult.getItems();
        ArrayList<PublishVO> vos = new ArrayList<>();
        for (Publish publish : items) {
            //把userInfo的数据转换到publishVO中
            PublishVO publishVO = new PublishVO();
            UserInfo userInfo = userInfoApi.findUserInfo(publish.getUserId());
            BeanUtils.copyProperties(userInfo, publishVO);
            publishVO.setUserId(publish.getUserId());
            publishVO.setId(publish.getId().toHexString());
            String value = redisTemplate.opsForValue().get("like_" + user.getId() + "publish_" + publish.getId());
            if (value == null) {
                publishVO.setHasLiked(0);
            } else {
                publishVO.setHasLiked(1);
            }
            String value1 = redisTemplate.opsForValue().get("like_" + user.getId() + "publish_" + publish.getId());
            if (value1 == null) {
                publishVO.setHasLoved(0);
            } else {
                publishVO.setHasLoved(1);
            }
            if (userInfo.getTags() != null) {
                publishVO.setTags(userInfo.getTags().split(","));
            }
            //把publish中的数据转换到publishVO中
            BeanUtils.copyProperties(publish, publishVO);
            publishVO.setImageContent(publish.getMedias().toArray(new String[]{}));
            publishVO.setDistance("2米");
            publishVO.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));

            vos.add(publishVO);

        }
        pageResult.setItems(vos);
        //把信息转换为客户端需要的
        return ResponseEntity.ok(pageResult);
    }


    /**
     * 发布动态
     *
     * @param multipartFiles
     * @param publish
     * @return
     * @throws IOException
     */
    public ResponseEntity addMovements(MultipartFile[] multipartFiles, Publish publish) throws IOException {
        User user = UserHolder.getUser();
        //先把动态存到动态列表里
        ArrayList<String> paths = new ArrayList<>();
        for (MultipartFile multipartFile : multipartFiles) {
            String path = ossTemplate.upHeaderPhoto(multipartFile.getInputStream(), multipartFile.getOriginalFilename());
            paths.add(path);
        }

        publish.setUserId(user.getId());
        publish.setState(0);
        publish.setMedias(paths);
        String publishId = movementsApi.addMovements(publish);
        //发送消息
        rocketMQTemplate.convertAndSend("tanhua-publish", publishId);
        movementMQService.sendSavePublishMsg(publishId);

        return ResponseEntity.ok(null);
    }

    /**
     * 好友动态
     *
     * @param page
     * @param pagesize
     * @return
     */
    public ResponseEntity friendMovements(Integer page, Integer pagesize) {
        User user = UserHolder.getUser();
        PageResult pageResult = movementsApi.friendMovements(user.getId(), page, pagesize);
        List<Publish> items = pageResult.getItems();
        ArrayList<PublishVO> publishVOS = new ArrayList<>();
        for (Publish publish : items) {
            PublishVO publishVO = new PublishVO();
            UserInfo userInfo = userInfoApi.findUserInfo(publish.getUserId());
            BeanUtils.copyProperties(userInfo, publishVO);
            publishVO.setUserId(publish.getUserId());
            publishVO.setId(publish.getId().toHexString());
            String value = redisTemplate.opsForValue().get("like_" + user.getId() + "publish_" + publish.getId());
            if (value == null) {
                publishVO.setHasLiked(0);
            } else {
                publishVO.setHasLiked(1);
            }
            String value1 = redisTemplate.opsForValue().get("like_" + user.getId() + "publish_" + publish.getId());
            if (value1 == null) {
                publishVO.setHasLoved(0);
            } else {
                publishVO.setHasLoved(1);
            }
            if (userInfo.getTags() != null) {
                publishVO.setTags(userInfo.getTags().split(","));
            }
            BeanUtils.copyProperties(publish, publishVO);
            publishVO.setImageContent(publish.getMedias().toArray(new String[]{}));
            publishVO.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));
            publishVO.setDistance("20米");

            publishVOS.add(publishVO);
        }
        pageResult.setItems(publishVOS);
        return ResponseEntity.ok(pageResult);
    }

    /**
     * 用户动态
     *
     * @param page
     * @param pagesize
     * @param userId
     * @return
     */
    public ResponseEntity findMyMovements(Integer page, Integer pagesize, Long userId) {
        if (userId == null) {
            userId = UserHolder.getUser().getId();
        }
        PageResult pageResult = movementsApi.findMyMovements(userId, page, pagesize);
        List<Publish> items = pageResult.getItems();
        ArrayList<PublishVO> publishVOS = new ArrayList<>();
        System.out.println(items);
        ArrayList<String> strings = new ArrayList<>();
        System.out.println(strings);

            for (Publish publish : items) {
                if (publish==null){
                    continue;
                }
                PublishVO publishVO = new PublishVO();
                UserInfo userInfo = userInfoApi.findUserInfo(userId);
                BeanUtils.copyProperties(userInfo, publishVO);
                publishVO.setUserId(publish.getUserId());
                publishVO.setId(publish.getId().toHexString());
                String value = redisTemplate.opsForValue().get("like_" + userId + "publish_" + publish.getId());
                if (value == null) {
                    publishVO.setHasLiked(0);
                } else {
                    publishVO.setHasLiked(1);
                }
                String value1 = redisTemplate.opsForValue().get("like_" + userId + "publish_" + publish.getId());
                if (value1 == null) {
                    publishVO.setHasLoved(0);
                } else {
                    publishVO.setHasLoved(1);
                }
                if (userInfo.getTags() != null) {
                    publishVO.setTags(userInfo.getTags().split(","));
                }
                BeanUtils.copyProperties(publish, publishVO);
                publishVO.setImageContent(publish.getMedias().toArray(new String[]{}));
                publishVO.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));
                publishVO.setDistance("20米");

                publishVOS.add(publishVO);
            }
            pageResult.setItems(publishVOS);
            return ResponseEntity.ok(pageResult);





    }

    /**
     * 给动态点赞
     *
     * @param publishId
     * @return
     */
    public ResponseEntity like(String publishId) {

        User user = UserHolder.getUser();
        Comment comment = new Comment();
        comment.setPubType(1);
        comment.setPublishId(new ObjectId(publishId));
        comment.setCommentType(1);
        comment.setUserId(user.getId());
        Publish publish = publishApi.findById(publishId);
        comment.setPublishUserId(publish.getUserId());
        int likeCount = commentApi.save(comment);
        redisTemplate.opsForValue().set("like_" + user.getId() + "publish_" + publishId, "2");
        //发送消息
        movementMQService.sendLikePublishMsg(publishId);
        log.info("发送消息:   publishId:{}", publishId);
        return ResponseEntity.ok(likeCount);

    }

    /**
     * 动态取消点赞
     *
     * @param publishId
     * @return
     */
    public ResponseEntity disLike(String publishId) {
        User user = UserHolder.getUser();
        Comment comment = new Comment();
        comment.setPubType(1);
        comment.setPublishId(new ObjectId(publishId));
        comment.setCommentType(1);
        comment.setUserId(user.getId());
        int likeCount = commentApi.remove(comment);
        redisTemplate.delete("like_" + user.getId() + "publish_" + publishId);
        //发送消息
        movementMQService.sendUnlikePublishMsg(publishId);
        return ResponseEntity.ok(likeCount);
    }

    /**
     * 喜欢动态
     *
     * @param publishId
     * @return
     */
    public ResponseEntity love(String publishId) {
        User user = UserHolder.getUser();
        Comment comment = new Comment();
        comment.setPubType(1);
        comment.setPublishId(new ObjectId(publishId));
        comment.setCommentType(3);
        comment.setUserId(user.getId());
        Publish publish = publishApi.findById(publishId);
        comment.setPublishUserId(publish.getUserId());
        int likeCount = commentApi.save(comment);
        redisTemplate.opsForValue().set("love_" + user.getId() + "publish_" + publishId, "2");
        //发送消息
        movementMQService.sendLovePublishMsg(publishId);
        return ResponseEntity.ok(likeCount);
    }

    /**
     * 取消喜欢
     *
     * @param publishId
     * @return
     */
    public ResponseEntity unlove(String publishId) {
        User user = UserHolder.getUser();
        Comment comment = new Comment();
        comment.setPubType(1);
        comment.setPublishId(new ObjectId(publishId));
        comment.setCommentType(3);
        comment.setUserId(user.getId());
        int likeCount = commentApi.remove(comment);
        redisTemplate.delete("love_" + user.getId() + "publish_" + publishId);
        //发送消息
        movementMQService.sendUnlovePublishMsg(publishId);
        return ResponseEntity.ok(likeCount);
    }

    /**
     * 用户动态详情
     *
     * @param publishId
     * @return
     */
    public ResponseEntity oneMovement(String publishId) {
        User user = UserHolder.getUser();
        Publish publish = movementsApi.oneMovment(publishId);
        PublishVO publishVO = new PublishVO();
        UserInfo userInfo = userInfoApi.findUserInfo(publish.getUserId());
        BeanUtils.copyProperties(userInfo, publishVO);
        publishVO.setUserId(publish.getUserId());
        publishVO.setId(publish.getId().toHexString());
        if (userInfo.getTags() != null) {
            publishVO.setTags(userInfo.getTags().split(","));
        }
        BeanUtils.copyProperties(publish, publishVO);
        publishVO.setImageContent(publish.getMedias().toArray(new String[]{}));
        publishVO.setDistance(RelativeDateFormat.format(new Date(publish.getCreated())));
        String value = redisTemplate.opsForValue().get("like_" + user.getId() + "publish_" + publishId);
        if (value == null) {
            publishVO.setHasLiked(0);
        } else {
            publishVO.setHasLiked(1);
        }
        String value1 = redisTemplate.opsForValue().get("like_" + user.getId() + "publish_" + publishId);
        if (value1 == null) {
            publishVO.setHasLoved(0);
        } else {
            publishVO.setHasLoved(1);
        }
        return ResponseEntity.ok(publishVO);
    }

    /**
     * 最近来访
     *
     * @return
     */
    public ResponseEntity visitors() {
        User user = UserHolder.getUser();
        String time = redisTemplate.opsForValue().get("time_visitor" + user.getId());
        List<Visitor> visitors = null;
        if (time != null) {
            visitors = visitorsApi.secvisitors(user.getId(), System.currentTimeMillis());
        } else {
            visitors = visitorsApi.visitors(user.getId());
        }
        redisTemplate.opsForValue().set("time_visitor" + user.getId(), String.valueOf(System.currentTimeMillis()));
        ArrayList<VisitorVO> vos = new ArrayList<>();
        for (Visitor visitor : visitors) {
            VisitorVO vo = new VisitorVO();
            UserInfo userInfo = userInfoApi.findUserInfo(visitor.getVisitorUserId());
            BeanUtils.copyProperties(userInfo, vo);
            vos.add(vo);
        }

        return ResponseEntity.ok(vos);
    }


    /**
     * 在redis中查找大数据推荐的动态
     *
     * @return
     */
    private PageResult findPublishByRedis(Integer page, Integer pagesize) {
        String pidStr = redisTemplate.opsForValue().get("QUANZI_PUBLISH_RECOMMEND_" + UserHolder.getUser().getId());
        if (pidStr == null) {
            return null;
        }
        String[] pidArray = pidStr.split(",");
        int pages = (int) Math.ceil(pidArray.length * 1.0 / pagesize);
        if (page > pages) {
            page = pages;
        }
        int start = (page - 1) * pagesize;
        int end = start + pagesize;
        if (end > pidArray.length) {
            end = pidArray.length;
        }
        ArrayList<Long> pids = new ArrayList<>();
        for (int i = start; i < end; i++) {
            long pid = Long.parseLong(pidArray[i]);
            pids.add(pid);
        }
        List<Publish> publishList = publishApi.findPublishByPid(pids);
        return new PageResult(pidArray.length, pagesize, pages, page, publishList);
    }
}
